﻿/*!
* Chef Framework v0.1.1
* Copyright 2010, I-Technology.NET, http://chef.codeplex.com
* Distributed in whole under the terms of the MIT license
* http://www.opensource.org/licenses/mit-license.php 
* 
* Author
* Robert Hoffmann
*/

/// <reference path="jquery-1.4.1-vsdoc.js" />
/// <reference path="json2.js" />

jQuery.fn.extend({
    // render result with logic
    renderTemplate: function (data, filter, callBack) {
        console.time("render");
        
        // since we work on arrays of namevalue collections, add items to an array if it is all alone
        var Data = (data.length > 0) ? data : [data];

        // Assign the callback that handles the logic
        var Filter = arguments[1] || function (item, template) { return template; };

        // Assign the callback that is fired when all rendering is done
        var CallBack = arguments[2] || function () { };

        // Loop over the data
        for (i = 0; i < Data.length; i++) {
            // Buid template depending on which data property names we have
            // Todo: Need to fix this back up ...too much looping
            var Template = this.buildTemplate(this, Data);

            // now bind each data item to it's template equivalent
            for (var name in Template.elements) {
                // We rewrite some names to make them compatible with hypens on css side & underscore on data side
                // Like this we can use microformats conventions on css class names to bind data
                var dataName = name.replace("-", "_").toLowerCase();
                Template.elements[dataName].text(Data[i][dataName]);
            }

            // apply logic to template with current data item
            // might override some of the preset value, but thats normal
            Template.elements = Filter(Data[i], Template.elements);

            // We check if Directive() attached any events to the elements
            // Only then do we clone with clone(true), which is much slower
            // This checking adds almost 100ms on a loop of 400 items, but reduces the rendering by 3x if events "are" present
            var keepEvents = false;
            for (var name in Template.elements) {
                if (Template.elements[name].data("events"))
                    keepEvents = true;
            }

            this.append(Template.clone(keepEvents));
        }

        // execute callback & return this so we can continue chaining
        console.timeEnd("render");
        CallBack(this);
        return this;
    },

    // Buid template depending on which data property names we have
    buildTemplate: function (ele, data) {
        // We only need a sample of the 1st item
        var properties = data[0] || data;

        // get the inner template & make a copy of it
        // TODO: 1st div (will probably change)
        var template = ele.find("div:first").clone(true);

        // We map each subelement of the template that matches a data item to pieces, 
        // which holds a reference to itself for later manipulation
        template.elements = [];        
        for (var name in properties) {
            // We rewrite some names to make them compatible with hypens on css side & underscore on data side
            // Like this we can use microformats conventions on css class names to bind data
            var dataName = name.replace("-", "_").toLowerCase();
            var cssName  = name.replace("_", "-").toLowerCase();

            // find & map the element (template.dataName=element)
            template.elements[dataName] = template.find(".".concat(cssName));
        }

        return template;
    }
});